package com.grechur.wanandroidcompose.widget


import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import java.lang.Integer.max

@Composable
fun FlowRow(
    modifier: Modifier = Modifier,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    verticalSpacing: Dp = 0.dp,
    content: @Composable () -> Unit
) {
    Layout(modifier = modifier, content = content) { measurables, constraints ->
        val looseConstraints = constraints.copy(minWidth = 0, minHeight = 0)
        val verticalSpacingPx = verticalSpacing.roundToPx()
        val horizontalSpacingPx = horizontalArrangement.spacing.roundToPx()
        val maxWidth = constraints.maxWidth

        var currentY = 0
        var currentX = 0
        var rowMaxHeight = 0
        val rowHeights = mutableListOf<Int>()
        val rowYs = mutableListOf(currentY)
        var leftHeight = constraints.maxHeight
        val heightLimitedFlag = constraints.maxHeight != Constraints.Infinity
        val flowContents = mutableListOf<MutableList<Placeable>>(mutableListOf())
        var rowContents = flowContents[0]

        for (measurable in measurables) {
            var tempConstraints = looseConstraints
            if (heightLimitedFlag) {
                val tempWidth = measurable.minIntrinsicWidth(leftHeight)
                if (tempWidth + currentX > maxWidth) {
                    leftHeight -= rowMaxHeight
                }
                tempConstraints = looseConstraints.copy(maxHeight = leftHeight)
            }

            val placeable = measurable.measure(tempConstraints)
            if (placeable.width + currentX > maxWidth) {
                currentX = 0
                currentY += rowMaxHeight
                rowHeights.add(rowMaxHeight)
                rowYs.add(currentY)
                rowMaxHeight = 0
                if (currentY >= constraints.maxHeight) break

                rowContents = mutableListOf()
                flowContents.add(rowContents)
            }

            rowMaxHeight = max(placeable.height + verticalSpacingPx, rowMaxHeight)
            rowContents.add(placeable)
            currentX += placeable.width + horizontalSpacingPx
        }

        currentY += rowMaxHeight
        rowHeights.add(rowMaxHeight)

        layout(maxWidth, currentY) {
            flowContents.forEachIndexed { i, row ->
                val childrenWidths = IntArray(row.size) { j ->
                    row[j].width
                }
                val xPositions = IntArray(childrenWidths.size) { 0 }
                with(horizontalArrangement) {
                    arrange(
                        maxWidth,
                        childrenWidths,
                        layoutDirection,
                        xPositions
                    )
                }

                row.forEachIndexed { j, col ->
                    val yOffset = verticalAlignment.align(
                        size = 0,
                        space = rowHeights[i] - col.height
                    )

                    col.place(xPositions[j], rowYs[i] + yOffset)
                }
            }
        }
    }
}

@Preview
@Composable
fun FlowRowPreView() {
    val items = listOf<String>("afda","vgdafa","greagrea","eee","vgdafa","greagrea","eee","vgdafa","greagrea","eee","vgdafa","greagrea","eee","vgdafa","greagrea","eee","vgdafa","greagrea","eee")
    Column {
        FlowRow(modifier = Modifier.fillMaxSize()) {
            items.forEach {
                Button(onClick = {  }) {
                    Text(text = "$it")
                }
            }
        }
    }

}
